#coding=utf-8
'''
Created on 2010-10-20

@author: tongji
@contact: tongji@rekoo.com
@summary: some tools for get user log
'''
import sys
import types
from logconfig import *

def udpsender(server):
    import socket, sys
    printerrinfo = lambda s:sys.stderr.write(s+'\n')
    udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp_client.connect(server)
    
    def sender(data):
        try:
            udp_client.sendall(data) 
        except socket.error, err:
            printerrinfo("<UserStats Error> Cannot send log, check UDPServer. error info: %s" % err)
            
    return sender

udpserver = ('127.0.0.1', 9191)
output = udpsender(udpserver)

class Logger(object):
    '''日志对象，每个需要记录的视图执行之前都应该先创建这样一个对象，来记录用户行为'''
    def __init__(self):
        self.setformatter() # 设置日志格式
        self.resetdata() # 重置数据对象
        self.resetargs() # 重置前后状态数据
        self.setoutput(output) # 设置输出方式
        from datagetter import ARGSDATA, BASEDATA # 基础数据与用户前后参数获得的方法，后端程序员设定
        self.basegetter = BASEDATA
        self.argsgetter = ARGSDATA
    
    def getdata(self, key, request, *args, **kwargs):
        '''集合所有数据'''
        self.data.update(self.basegetter(key, request, *args, **kwargs))
        callback = whitelist.get(key, None) # 从配置中读取回调函数
        if callback is not None:
            self.data.update(callback(request, self.args, *args, **kwargs))
    
    def format(self, data):
        '''格式化数据'''
        delimiter = '\t'
        record = []
        for item in self.formatter:
            record.append(data.get(item, ''))
        return delimiter.join(map(str, record))

    def write(self):
        '''将数据写到规定的渠道'''
        if self.data['success']: # 如果最终成功标识位为真 则记录日志，否则不记录
            try:
                record = self.format(self.data)
            except Exception,e:
                print e
            else:
                self.output(record)

    def getargs(self, scene, request, *args, **kwargs):
        '''获取视图函数执行前后的一些数据状态'''
        self.args[scene] = self.argsgetter(request, *args, **kwargs)
    
    def resetargs(self):
        '''重置回调参数数据'''
        self.args = {'before':{}, 'after':{}}
    
    def resetdata(self):
        self.data = {}
    
    def setoutput(self, output=None):
        if output is not None:
            self.output = output
        else:
            self.output = sys.stdout.write
    
    def setformatter(self, formatter=['uid', 'scene', 'level', 'stay', 'action', 'v1', 'v2', 'v3', 'v4', 'num']):
        self.formatter = formatter

def userlog_decorate(view, key):
    '''用来装饰需要记录行为日志的视图函数'''
    def _userlog_decorate(request, *args, **kwargs):
        logger = Logger() # 建立一个日志对象
        logger.getargs('before', request, *args, **kwargs) # 日志对象获得执行之前的数据
        
        return_data = view(request, *args, **kwargs) # 执行视函数
        
        logger.getargs('after', request, *args, **kwargs) # 日志对象获得执行之后的数据
        logger.getdata(key, request, *args, **kwargs)
        logger.write() # 获取前后数据之后，记录日志
        return return_data
    return _userlog_decorate # 返回包装之后的视图函数对象


def install(module):
    '''
    装饰方法，用来装配配置好的视图函数，截取有用的数据
    '''
    for item in dir(module):
        attr = getattr(module, item)
        print 'the attr is ', item
        try:
            print 'GOT attr module : ', attr.__name__
        except:
            print 'no __name__ provided'
        if isinstance(attr, types.FunctionType):
            module_name = attr.__module__
            func_name = attr.func_name
            global_name = module_name + '.' + func_name
            if global_name in whitelist:
                try:
#                    setattr(module, func_name, userlog_decorate(attr, global_name))
                    module.__dict__.update({func_name:userlog_decorate(attr, global_name)})
                    print 'successfully install view : %s' % global_name
                except Exception, e:
                    print e

